package com.atguigu.srb.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.core.enums.LendStatusEnum;
import com.atguigu.srb.core.enums.TransTypeEnum;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.*;
import com.atguigu.srb.core.pojo.bo.TransFlowBO;
import com.atguigu.srb.core.pojo.entity.Lend;
import com.atguigu.srb.core.pojo.entity.LendItem;
import com.atguigu.srb.core.pojo.entity.LendItemReturn;
import com.atguigu.srb.core.pojo.entity.LendReturn;
import com.atguigu.srb.core.pojo.vo.TransferLendItemReturnVO;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.core.util.LendNoUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author Bright
 * @since 2022-04-09
 */
@Slf4j
@Service
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {
    @Resource
    UserAccountService userAccountService;
    @Resource
    UserAccountMapper userAccountMapper;
    @Resource
    UserBindMapper userBindMapper;
    @Resource
    LendMapper lendMapper;
    @Resource
    LendItemReturnService lendItemReturnService;
    @Resource
    LendItemMapper lendItemMapper;
    @Resource
    UserInfoMapper userInfoMapper;
    @Resource
    TransFlowService transFlowService;


    @Override
    public List<LendReturn> listByLendId(Long lendId) {
        QueryWrapper<LendReturn> lendReturnQueryWrapper = new QueryWrapper<>();
        lendReturnQueryWrapper.eq("lend_id", lendId);


        return baseMapper.selectList(lendReturnQueryWrapper);
    }

    @Override
    public String commitReturn(Long lendReturnId, Long userId) {
        //得到回款计划信息
        LendReturn lendReturn = baseMapper.selectById(lendReturnId);
        //判断登录用户信息是否正确
        Assert.equals(userId, lendReturn.getUserId(), ResponseEnum.WEIXIN_FETCH_USERINFO_ERROR);
        //判断还款计划状态
        Assert.equals(lendReturn.getStatus(), LendReturn.NOT_RETURNED, ResponseEnum.ERROR);
        //判断账号金额是否够用
        BigDecimal total = lendReturn.getTotal();
        BigDecimal account = userAccountService.getAccountByUserId(userId);
        Assert.isTrue(total.compareTo(account) <= 0, ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);
        //判断在此之前的所有的还款计划是否还款
        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        QueryWrapper<LendReturn> lendReturnQueryWrapper = new QueryWrapper<>();
        lendReturnQueryWrapper
                .eq("lend_id", lend.getId())
                .eq("status", LendReturn.NOT_RETURNED)
                .lt("current_period", lendReturn.getCurrentPeriod());
        Integer count = baseMapper.selectCount(lendReturnQueryWrapper);
        if (count > 0) {
            log.info("之前还款没结清........");
            Assert.isTrue(false, ResponseEnum.ERROR);
        }

        //组装参数
        HashMap<String, Object> paramMap = new HashMap<>(18);
        paramMap.put("agentId", HfbConst.AGENT_ID);
        //标的名称

        paramMap.put("agentGoodsName", lend.getTitle());
        //批次号
        paramMap.put("agentBatchNo", lendReturn.getReturnNo());
        String bindCode = userBindMapper.getBindCodeByUserId(userId);

        paramMap.put("fromBindCode", bindCode);
        paramMap.put("totalAmt", total);
        paramMap.put("note", "无");
        //创建回款明细项
        List<Map<String, Object>> lendItemReturnDetailList = lendItemReturnService.addReturnDetail(lendReturnId);

        paramMap.put("data", JSONObject.toJSONString(lendItemReturnDetailList));
        paramMap.put("voteFeeAmt", new BigDecimal(0));
        paramMap.put("returnUrl", HfbConst.BORROW_RETURN_RETURN_URL);
        paramMap.put("notifyUrl", HfbConst.BORROW_RETURN_NOTIFY_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        paramMap.put("sign", RequestHelper.getSign(paramMap));

        return FormHelper.buildForm(HfbConst.BORROW_RETURN_URL, paramMap);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String notifyReturn(Map<String, Object> paramMap) {
        String agentBatchNo = paramMap.get("agentBatchNo").toString();
        //幂等性返回
        if (transFlowService.isTransFlow(agentBatchNo)) {
            log.info("幂等性返回");
            return "fail";

        }
        //查询还款计划项
        //还款批次号
        QueryWrapper<LendReturn> lendReturnQueryWrapper = new QueryWrapper<>();
        lendReturnQueryWrapper.eq("return_no", agentBatchNo);
        LendReturn lendReturn = baseMapper.selectOne(lendReturnQueryWrapper);

        Lend lend = lendMapper.selectById(lendReturn.getLendId());

        //扣除借款人账户金额
        Long userId = lendReturn.getUserId();
        BigDecimal totalAmt = new BigDecimal(paramMap.get("totalAmt").toString());
        userAccountMapper.updateAccountByUserId(userId, totalAmt.negate(), new BigDecimal(0));

        //生成还款流水
        String bindCode = userBindMapper.getBindCodeByUserId(userId);
        String resultMsg = paramMap.get("resultMsg").toString();
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBatchNo,
                bindCode,
                totalAmt,
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());

        transFlowService.saveTransFlow(transFlowBO);


        //判断是否为最后一次还款(是：修改标的状态)

        if (lendReturn.getLast()) {

            lend.setStatus(LendStatusEnum.PAY_OK.getStatus());
            lendMapper.updateById(lend);
        }

        //更新还款计划
        //判断是否预期
        LocalDate returnDate = lendReturn.getReturnDate();
        LocalDate now = LocalDate.now();
        lendReturn.setRealReturnTime(LocalDateTime.now());
        lendReturn.setOverdue(!now.isBefore(returnDate));
        lendReturn.setStatus(LendReturn.RETURNED);
        baseMapper.updateById(lendReturn);


        //获得回款计划列表
        List<LendItemReturn> lendItemReturns = lendItemReturnService.listByLendReturnId(lendReturn.getId());

        lendItemReturns.forEach(lendItemReturn -> {
            //投资人账户回款
            BigDecimal total = lendItemReturn.getTotal();
            String investBindCode = userBindMapper.getBindCodeByUserId(lendItemReturn.getInvestUserId());
            userAccountMapper.updateAccount(investBindCode, total, new BigDecimal(0));
            //生成回款流水
            TransFlowBO investTransFlowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    total,
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
            transFlowService.saveTransFlow(investTransFlowBO);

            //判断是否为最后一次回款（是：修改投资项状态）
            LendItem lendItem = lendItemMapper.selectById(lendItemReturn.getLendItemId());
            if (lendReturn.getLast()) {
                lendItem.setStatus(LendItem.REPAID);
            }
            lendItem.setRealAmount(total);
            lendItemMapper.updateById(lendItem);

            //更新回款计划
            LocalDate itemReturnDate = lendItemReturn.getReturnDate();
            //判断是否预期
            boolean overdu = itemReturnDate.isBefore(LocalDate.now());
            lendItemReturn.setOverdue(overdu);
            if (overdu) {
                lendItemReturn.setOverdueTotal(total);
            }
            lendItemReturn.setRealReturnTime(LocalDateTime.now());
            lendItemReturn.setStatus(LendItemReturn.RETURNED);
            lendItemReturnService.updateById(lendItemReturn);

        });
        return "success";
    }
}
